package apigateway.project.core.filter.loadbalance;

import apigateway.project.commen.config.Rule;
import apigateway.project.commen.config.ServiceInstance;
import apigateway.project.commen.exception.NotFoundException;
import apigateway.project.core.context.GlobalContext;
import apigateway.project.core.filter.Filter;
import apigateway.project.core.request.GlobalRequest;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;

import java.util.Map;

import static apigateway.project.commen.constant.FilterConst.*;
import static apigateway.project.commen.enums.ResponseCode.SERVICE_INSTANCE_NOT_FOUND;

@Slf4j
public class LoadBalanceFilter implements Filter {
    @Override
    public void doFilter(GlobalContext ctx) throws Exception {
        //获得某一个服务实例
        ServiceInstance serviceInstance = getServiceInstance(ctx);
        System.out.println("IP为" + serviceInstance.getIp() + ",端口号：" + serviceInstance.getPort());
        GlobalRequest request = ctx.getRequest();
        if (serviceInstance != null && request != null) {
            String host = serviceInstance.getIp() + ":" + serviceInstance.getPort();
            request.setModifyHost(host);
        } else {
            log.warn("No instance available for :{}", ctx.getRule().getServiceName());
            throw new NotFoundException(SERVICE_INSTANCE_NOT_FOUND);
        }
    }

    /**
     * 选择负载均衡算法获取服务实例
     */
    public ServiceInstance getServiceInstance(GlobalContext ctx){
        ServiceInstance serviceInstance = null;
        Rule.LoadBalanceConfig loadBalanceConfig = ctx.getRule().getLoadBalanceConfig();
        //没有这个负载均衡配置
        if(loadBalanceConfig==null){
            return null;
        }

        if(LOAD_BALANCE_FILTER_ID.equals(loadBalanceConfig.getId())){
            String config = loadBalanceConfig.getConfig();
            //默认使用轮询负载均衡器
            String strategy = LOAD_BALANCE_STRATEGY_ROUND_ROBIN;
            if (StringUtils.isNotEmpty(config)) {
                Map<String, String> mapTypeMap = JSON.parseObject(config, Map.class);
                //如果找到LOAD_BALANCE_KEY对应的值，则替换默认的值
                strategy = mapTypeMap.getOrDefault(LOAD_BALANCE_KEY,strategy);
            }
            switch (strategy){
                case LOAD_BALANCE_STRATEGY_ROUND_ROBIN:
                    serviceInstance = new RoundRobinLoadBalanceRule().choose(ctx.getRule().getServiceName());
                    break;
                case LOAD_BALANCE_STRATEGY_RANDOM:
                    serviceInstance = new RandomLoadBalanceRule().choose(ctx.getRule().getServiceName());
                    break;
                case LOAD_BALANCE_STRATEGY_IPHASH:
                    serviceInstance = new IPHashLoadBalanceRule().choose(ctx);
                case LOAD_BALANCE_STRATEGY_CONSISTENTHASH:
                    serviceInstance = new ConsistentHashLoadBalanceRule().choose(ctx);
                case LOAD_BALANCE_STRATEGY_WEIGHT:
                    serviceInstance = new WeightLoadBalanceRule().choose(ctx.getRule().getServiceName());
                default:
                    log.warn("No loadBalance strategy for service:{}", strategy);
                    serviceInstance = new RandomLoadBalanceRule().choose(ctx.getRule().getServiceName());
                    break;
            }
        }
        return serviceInstance;
    }
}
